using Microsoft.Extensions.Logging;
using SumerCoreDevOps.Domain.Entities;
using SumerCoreDevOps.Infrastructure.Data;

namespace SumerCoreDevOps.Infrastructure.Identity;

/// <summary>
/// 角色管理器
/// </summary>
public class RoleManager
{
    private readonly FreeSQLProvider _dbProvider;
    private readonly ILogger<RoleManager> _logger;

    public RoleManager(FreeSQLProvider dbProvider, ILogger<RoleManager> logger)
    {
        _dbProvider = dbProvider;
        _logger = logger;
    }

    /// <summary>
    /// 创建角色
    /// </summary>
    public async Task<Role> CreateRoleAsync(
        string roleName,
        string? description = null,
        string? createdBy = null)
    {
        // 检查角色名是否已存在
        var existingRole = await _dbProvider.Orm.Select<Role>()
            .Where(r => r.RoleName == roleName)
            .FirstAsync();

        if (existingRole != null)
        {
            throw new InvalidOperationException("角色名已存在");
        }

        var role = new Role
        {
            RoleName = roleName,
            Description = description,
            IsSystem = false,
            IsEnabled = true,
            CreatedAt = DateTime.UtcNow,
            CreatedBy = createdBy
        };

        await _dbProvider.Orm.Insert(role).ExecuteAffrowsAsync();
        _logger.LogInformation("创建角色成功: {RoleName}", roleName);

        return role;
    }

    /// <summary>
    /// 更新角色
    /// </summary>
    public async Task UpdateRoleAsync(
        long roleId,
        string? roleName = null,
        string? description = null,
        bool? isEnabled = null,
        string? updatedBy = null)
    {
        var role = await _dbProvider.Orm.Select<Role>()
            .Where(r => r.Id == roleId)
            .FirstAsync();

        if (role == null)
        {
            throw new InvalidOperationException("角色不存在");
        }

        if (role.IsSystem)
        {
            throw new InvalidOperationException("系统角色不允许修改");
        }

        // 检查新角色名是否冲突
        if (!string.IsNullOrEmpty(roleName) && roleName != role.RoleName)
        {
            var existingRole = await _dbProvider.Orm.Select<Role>()
                .Where(r => r.RoleName == roleName && r.Id != roleId)
                .FirstAsync();

            if (existingRole != null)
            {
                throw new InvalidOperationException("角色名已存在");
            }

            role.RoleName = roleName;
        }

        if (description != null)
        {
            role.Description = description;
        }

        if (isEnabled.HasValue)
        {
            role.IsEnabled = isEnabled.Value;
        }

        role.UpdatedAt = DateTime.UtcNow;
        role.UpdatedBy = updatedBy;

        await _dbProvider.Orm.Update<Role>()
            .SetSource(role)
            .ExecuteAffrowsAsync();

        _logger.LogInformation("更新角色成功: RoleId={RoleId}", roleId);
    }

    /// <summary>
    /// 删除角色
    /// </summary>
    public async Task DeleteRoleAsync(long roleId)
    {
        var role = await _dbProvider.Orm.Select<Role>()
            .Where(r => r.Id == roleId)
            .FirstAsync();

        if (role == null)
        {
            throw new InvalidOperationException("角色不存在");
        }

        if (role.IsSystem)
        {
            throw new InvalidOperationException("系统角色不允许删除");
        }

        // 检查是否有用户关联此角色
        var userCount = await _dbProvider.Orm.Select<UserRole>()
            .Where(ur => ur.RoleId == roleId)
            .CountAsync();

        if (userCount > 0)
        {
            throw new InvalidOperationException($"角色下还有 {userCount} 个用户，无法删除");
        }

        // 删除角色的所有权限关联
        await _dbProvider.Orm.Delete<RolePermission>()
            .Where(rp => rp.RoleId == roleId)
            .ExecuteAffrowsAsync();

        // 删除角色
        await _dbProvider.Orm.Delete<Role>()
            .Where(r => r.Id == roleId)
            .ExecuteAffrowsAsync();

        _logger.LogInformation("删除角色成功: RoleId={RoleId}", roleId);
    }

    /// <summary>
    /// 获取角色（包含权限）
    /// </summary>
    public async Task<Role?> GetRoleByIdAsync(long roleId)
    {
        var role = await _dbProvider.Orm.Select<Role>()
            .Where(r => r.Id == roleId)
            .FirstAsync();

        if (role == null)
        {
            return null;
        }

        // 手动加载权限关联
        var permissions = await _dbProvider.Orm.Select<Permission>()
            .InnerJoin<RolePermission>((p, rp) => p.Id == rp.PermissionId)
            .Where<RolePermission>(rp => rp.RoleId == roleId)
            .ToListAsync();

        role.Permissions = permissions;
        return role;
    }

    /// <summary>
    /// 获取所有角色
    /// </summary>
    public async Task<List<Role>> GetAllRolesAsync(bool includePermissions = false)
    {
        var roles = await _dbProvider.Orm.Select<Role>()
            .OrderByDescending(r => r.CreatedAt)
            .ToListAsync();

        if (includePermissions)
        {
            // 批量加载所有角色的权限
            var roleIds = roles.Select(r => r.Id).ToList();
            if (roleIds.Any())
            {
                var rolePermissions = await _dbProvider.Orm.Select<Permission>()
                    .InnerJoin<RolePermission>((p, rp) => p.Id == rp.PermissionId)
                    .Where<RolePermission>(rp => roleIds.Contains(rp.RoleId))
                    .ToListAsync<(Permission permission, RolePermission rp)>();

                // 分组并赋值
                var permissionGroups = rolePermissions
                    .GroupBy(x => x.rp.RoleId)
                    .ToDictionary(g => g.Key, g => g.Select(x => x.permission).ToList());

                foreach (var role in roles)
                {
                    role.Permissions = permissionGroups.ContainsKey(role.Id)
                        ? permissionGroups[role.Id]
                        : new List<Permission>();
                }
            }
        }

        return roles;
    }

    /// <summary>
    /// 为角色分配权限
    /// </summary>
    public async Task AssignPermissionToRoleAsync(
        long roleId,
        long permissionId,
        string? assignedBy = null)
    {
        var role = await _dbProvider.Orm.Select<Role>()
            .Where(r => r.Id == roleId)
            .FirstAsync();

        if (role == null)
        {
            throw new InvalidOperationException("角色不存在");
        }

        var permission = await _dbProvider.Orm.Select<Permission>()
            .Where(p => p.Id == permissionId)
            .FirstAsync();

        if (permission == null)
        {
            throw new InvalidOperationException("权限不存在");
        }

        // 检查是否已分配
        var existing = await _dbProvider.Orm.Select<RolePermission>()
            .Where(rp => rp.RoleId == roleId && rp.PermissionId == permissionId)
            .FirstAsync();

        if (existing != null)
        {
            _logger.LogWarning("权限已分配给角色: RoleId={RoleId}, PermissionId={PermissionId}", roleId, permissionId);
            return;
        }

        var rolePermission = new RolePermission
        {
            RoleId = roleId,
            PermissionId = permissionId,
            AssignedAt = DateTime.UtcNow,
            AssignedBy = assignedBy
        };

        await _dbProvider.Orm.Insert(rolePermission).ExecuteAffrowsAsync();
        _logger.LogInformation("为角色分配权限成功: RoleId={RoleId}, PermissionId={PermissionId}", roleId, permissionId);
    }

    /// <summary>
    /// 批量为角色分配权限
    /// </summary>
    public async Task AssignPermissionsToRoleAsync(
        long roleId,
        List<long> permissionIds,
        string? assignedBy = null)
    {
        var role = await _dbProvider.Orm.Select<Role>()
            .Where(r => r.Id == roleId)
            .FirstAsync();

        if (role == null)
        {
            throw new InvalidOperationException("角色不存在");
        }

        // 检查所有权限是否存在
        var permissions = await _dbProvider.Orm.Select<Permission>()
            .Where(p => permissionIds.Contains(p.Id))
            .ToListAsync();

        if (permissions.Count != permissionIds.Count)
        {
            throw new InvalidOperationException("部分权限不存在");
        }

        // 获取已存在的权限关联
        var existingPermissions = await _dbProvider.Orm.Select<RolePermission>()
            .Where(rp => rp.RoleId == roleId && permissionIds.Contains(rp.PermissionId))
            .ToListAsync();

        var existingPermissionIds = existingPermissions.Select(rp => rp.PermissionId).ToList();

        // 只插入不存在的权限关联
        var newPermissionIds = permissionIds.Except(existingPermissionIds).ToList();

        if (newPermissionIds.Any())
        {
            var rolePermissions = newPermissionIds.Select(permissionId => new RolePermission
            {
                RoleId = roleId,
                PermissionId = permissionId,
                AssignedAt = DateTime.UtcNow,
                AssignedBy = assignedBy
            }).ToList();

            await _dbProvider.Orm.Insert(rolePermissions).ExecuteAffrowsAsync();
            _logger.LogInformation("为角色批量分配权限成功: RoleId={RoleId}, Count={Count}", roleId, newPermissionIds.Count);
        }
    }

    /// <summary>
    /// 撤销角色权限
    /// </summary>
    public async Task RevokePermissionFromRoleAsync(long roleId, long permissionId)
    {
        var deleted = await _dbProvider.Orm.Delete<RolePermission>()
            .Where(rp => rp.RoleId == roleId && rp.PermissionId == permissionId)
            .ExecuteAffrowsAsync();

        if (deleted > 0)
        {
            _logger.LogInformation("撤销角色权限成功: RoleId={RoleId}, PermissionId={PermissionId}", roleId, permissionId);
        }
        else
        {
            _logger.LogWarning("未找到角色权限关联: RoleId={RoleId}, PermissionId={PermissionId}", roleId, permissionId);
        }
    }

    /// <summary>
    /// 为用户分配角色
    /// </summary>
    public async Task AssignRoleToUserAsync(
        long userId,
        long roleId,
        string? assignedBy = null)
    {
        var user = await _dbProvider.Orm.Select<User>()
            .Where(u => u.Id == userId)
            .FirstAsync();

        if (user == null)
        {
            throw new InvalidOperationException("用户不存在");
        }

        var role = await _dbProvider.Orm.Select<Role>()
            .Where(r => r.Id == roleId)
            .FirstAsync();

        if (role == null)
        {
            throw new InvalidOperationException("角色不存在");
        }

        if (!role.IsEnabled)
        {
            throw new InvalidOperationException("角色未启用");
        }

        // 检查是否已分配
        var existing = await _dbProvider.Orm.Select<UserRole>()
            .Where(ur => ur.UserId == userId && ur.RoleId == roleId)
            .FirstAsync();

        if (existing != null)
        {
            _logger.LogWarning("角色已分配给用户: UserId={UserId}, RoleId={RoleId}", userId, roleId);
            return;
        }

        var userRole = new UserRole
        {
            UserId = userId,
            RoleId = roleId,
            AssignedAt = DateTime.UtcNow,
            AssignedBy = assignedBy
        };

        await _dbProvider.Orm.Insert(userRole).ExecuteAffrowsAsync();
        _logger.LogInformation("为用户分配角色成功: UserId={UserId}, RoleId={RoleId}", userId, roleId);
    }

    /// <summary>
    /// 撤销用户角色
    /// </summary>
    public async Task RevokeRoleFromUserAsync(long userId, long roleId)
    {
        var deleted = await _dbProvider.Orm.Delete<UserRole>()
            .Where(ur => ur.UserId == userId && ur.RoleId == roleId)
            .ExecuteAffrowsAsync();

        if (deleted > 0)
        {
            _logger.LogInformation("撤销用户角色成功: UserId={UserId}, RoleId={RoleId}", userId, roleId);
        }
        else
        {
            _logger.LogWarning("未找到用户角色关联: UserId={UserId}, RoleId={RoleId}", userId, roleId);
        }
    }

    /// <summary>
    /// 获取角色的所有用户
    /// </summary>
    public async Task<List<User>> GetUsersByRoleIdAsync(long roleId)
    {
        return await _dbProvider.Orm.Select<User>()
            .InnerJoin<UserRole>((u, ur) => u.Id == ur.UserId)
            .Where<UserRole>(ur => ur.RoleId == roleId)
            .OrderByDescending(u => u.CreatedAt)
            .ToListAsync();
    }
}
